package object

// NewEnclosedEnvironment 实例化一个函数内部的环境，outer是外部环境
func NewEnclosedEnvironment(outer *Environment) *Environment {
	env := NewEnvironment()
	env.outer = outer
	return env
}

// NewEnvironment 实例化环境
func NewEnvironment() *Environment {
	store := make(map[string]Object)
	return &Environment{store: store, outer: nil}
}

// Environment 环境结构体，store是变量的集合，outer一般是用在函数内部的，指向函数外部的变量的集合
type Environment struct {
	store map[string]Object
	outer *Environment
}

// Get 获取存储在环境中的变量，先在store中获取，如果有，直接返回，如果没有，有外部环境，去外部获取
// 注意：这样设计是为了把函数的作用域和函数外的全部作用域区分开，在函数内是优先从函数内的环境中获取变量的
func (e *Environment) Get(name string) (Object, bool) {
	obj, ok := e.store[name]
	if !ok && e.outer != nil {
		obj, ok = e.outer.Get(name)
	}
	return obj, ok
}

// Set 设置变量进入环境，设置变量时，是直接设置进store即可
// 设置变量就两种情况：第一种是函数外，这中就直接设置就行了；第二种是函数内，这种是设置进store，也就是函数内的环境
func (e *Environment) Set(name string, val Object) Object {
	e.store[name] = val
	return val
}
